nanopyx.core.generate.beads
1import numpy as np 2from math import sqrt 3from skimage.filters import gaussian 4from skimage.transform import EuclideanTransform, warp 5 6from ..transform.blocks import assemble_frame_from_blocks 7 8 9def generate_random_position(n_rows, n_cols): 10 """ 11 Generates a random position given number of rows and columns. 12 :param n_rows: int; number of rows 13 :param n_cols: int; number of columns 14 :return: int, int; random position constrained to 0.1 and 0.9 of n_rows and n_cols 15 """ 16 17 min_r = int(n_rows * 0.1) 18 max_r = int(n_rows * 0.9) 19 20 min_c = int(n_cols * 0.1) 21 max_c = int(n_cols * 0.9) 22 23 r = np.random.randint(min_r, max_r) 24 c = np.random.randint(min_c, max_c) 25 26 return r, c 27 28def generate_image(n_objects=10, shape=(2, 300, 300), dtype=np.float16): 29 """ 30 Generates a random image with objects in random positions 31 :param n_objects: int; number of objects to generate 32 :param shape: tuple; with shape (z, y, x) 33 :param dtype: data type to be used in the generated numpy array 34 :return: numpy array with shape (z, y, x) and defined data type and n_objects 35 """ 36 37 img = np.zeros(shape).astype(dtype) 38 39 n_rows = img.shape[1] 40 n_cols = img.shape[2] 41 42 for i in range(n_objects): 43 r, c = generate_random_position(n_rows, n_cols) 44 img[:, r, c] = np.finfo(np.float16).max 45 46 for i in range(img.shape[0]): 47 img[i] = gaussian(img[i], sigma=3) 48 49 return img 50 51def generate_timelapse_drift(n_objects=10, shape=(10, 300, 300), dtype=np.float16, drift=None, 52 drift_mode="directional"): 53 """ 54 Generate random timelapse image with drift over time. 55 :param n_objects: int; number of objects to generate 56 :param shape: tuple; with shape (t, y, x) 57 :param dtype: data type to be used in the generated numpy array 58 :param drift: None or int; number of pixels corresponding to drift between frames. If None, automatic drift is 59 calculated based on 0.02 of image dimensions. 60 :param drift_mode: str; "directional" (default) or "random"; 61 :return: numpy array with shape (t, y, x) and defined data type and n_objects 62 """ 63 64 if drift is None: 65 drift = min(shape[1]*0.02, shape[2]*0.02) 66 67 img = generate_image(n_objects=n_objects, shape=shape, dtype=dtype) 68 69 if drift_mode == "directional": 70 transformation_matrix = EuclideanTransform(translation=(-drift, -drift)) 71 for i in range(shape[0]-1): 72 img[i+1] = warp(img[i], transformation_matrix.inverse, order=3, preserve_range=True) 73 74 elif drift_mode == "random": 75 for i in range(shape[0]-1): 76 77 state = np.random.randint(0, 3) 78 79 if state == 1: 80 transformation_matrix = EuclideanTransform(translation=(-sqrt(drift), -sqrt(drift))) 81 elif state == 2: 82 transformation_matrix = EuclideanTransform(translation=(-sqrt(drift), sqrt(drift))) 83 elif state == 3: 84 transformation_matrix = EuclideanTransform(translation=(sqrt(drift), -sqrt(drift))) 85 else: 86 transformation_matrix = EuclideanTransform(translation=(sqrt(drift), sqrt(drift))) 87 88 img[i+1] = warp(img[i], transformation_matrix.inverse, order=3, preserve_range=True) 89 90 return img 91 92def generate_channel_misalignment(): 93 """ 94 Generates an image with shape (3, 300, 300) with 1 object centered on each 3x3 block of the image. 95 Slices corresponding to channel 2 and 3 are shifted relative to channel 1 (template). 96 :return: numpy array of shape (3, 300, 300) corresponding to a random image with misalignment between channels. 97 """ 98 99 n_blocks = 3 100 h = 300 101 w = 300 102 103 block_img = np.zeros((int(h/n_blocks), int(w/n_blocks))) 104 block_h = int(h / n_blocks) 105 block_w = int(w / n_blocks) 106 block_img[int(block_h/2), int(block_w/2)] = 1 107 block_img = gaussian(block_img, sigma=3) 108 109 ref_channel = np.zeros((h, w)) 110 misaligned_blocks = [] 111 misaligned_blocks_2 = [] 112 113 for x_i in range(n_blocks): 114 for y_i in range(n_blocks): 115 ref_channel[y_i*block_h:y_i*block_h+block_h, x_i*block_w:x_i*block_w+block_w] += block_img 116 117 misalignments = [(-3, -3), (-3, 0), (-3, 3), (0, -3), (0, 0), (0, 3), (3, -3), (3, 0), (3, 3)] 118 119 for mis in misalignments: 120 block_img = np.zeros((int(h/n_blocks), int(w/n_blocks))) 121 block_h = h / n_blocks 122 block_w = w / n_blocks 123 block_img[int(block_h/2)+mis[0], int(block_w/2)+mis[1]] = 1 124 block_img = gaussian(block_img, sigma=3) 125 misaligned_blocks.append(block_img) 126 127 misalignments.reverse() 128 129 for mis in misalignments: 130 block_img = np.zeros((int(h/n_blocks), int(w/n_blocks))) 131 block_h = h / n_blocks 132 block_w = w / n_blocks 133 block_img[int(block_h/2)+mis[0], int(block_w/2)+mis[1]] = 1 134 block_img = gaussian(block_img, sigma=3) 135 misaligned_blocks_2.append(block_img) 136 137 misaligned_channel = assemble_frame_from_blocks(np.array(misaligned_blocks), 3, 3) 138 misaligned_channel_2 = assemble_frame_from_blocks(np.array(misaligned_blocks_2), 3, 3) 139 140 return np.array([ref_channel, misaligned_channel, misaligned_channel_2]).astype(np.float16)
def
generate_random_position(n_rows, n_cols):
10def generate_random_position(n_rows, n_cols): 11 """ 12 Generates a random position given number of rows and columns. 13 :param n_rows: int; number of rows 14 :param n_cols: int; number of columns 15 :return: int, int; random position constrained to 0.1 and 0.9 of n_rows and n_cols 16 """ 17 18 min_r = int(n_rows * 0.1) 19 max_r = int(n_rows * 0.9) 20 21 min_c = int(n_cols * 0.1) 22 max_c = int(n_cols * 0.9) 23 24 r = np.random.randint(min_r, max_r) 25 c = np.random.randint(min_c, max_c) 26 27 return r, c
Generates a random position given number of rows and columns.
Parameters
- n_rows: int; number of rows
- n_cols: int; number of columns
Returns
int, int; random position constrained to 0.1 and 0.9 of n_rows and n_cols
def
generate_image(n_objects=10, shape=(2, 300, 300), dtype=<class 'numpy.float16'>):
29def generate_image(n_objects=10, shape=(2, 300, 300), dtype=np.float16): 30 """ 31 Generates a random image with objects in random positions 32 :param n_objects: int; number of objects to generate 33 :param shape: tuple; with shape (z, y, x) 34 :param dtype: data type to be used in the generated numpy array 35 :return: numpy array with shape (z, y, x) and defined data type and n_objects 36 """ 37 38 img = np.zeros(shape).astype(dtype) 39 40 n_rows = img.shape[1] 41 n_cols = img.shape[2] 42 43 for i in range(n_objects): 44 r, c = generate_random_position(n_rows, n_cols) 45 img[:, r, c] = np.finfo(np.float16).max 46 47 for i in range(img.shape[0]): 48 img[i] = gaussian(img[i], sigma=3) 49 50 return img
Generates a random image with objects in random positions
Parameters
- n_objects: int; number of objects to generate
- shape: tuple; with shape (z, y, x)
- dtype: data type to be used in the generated numpy array
Returns
numpy array with shape (z, y, x) and defined data type and n_objects
def
generate_timelapse_drift( n_objects=10, shape=(10, 300, 300), dtype=<class 'numpy.float16'>, drift=None, drift_mode='directional'):
52def generate_timelapse_drift(n_objects=10, shape=(10, 300, 300), dtype=np.float16, drift=None, 53 drift_mode="directional"): 54 """ 55 Generate random timelapse image with drift over time. 56 :param n_objects: int; number of objects to generate 57 :param shape: tuple; with shape (t, y, x) 58 :param dtype: data type to be used in the generated numpy array 59 :param drift: None or int; number of pixels corresponding to drift between frames. If None, automatic drift is 60 calculated based on 0.02 of image dimensions. 61 :param drift_mode: str; "directional" (default) or "random"; 62 :return: numpy array with shape (t, y, x) and defined data type and n_objects 63 """ 64 65 if drift is None: 66 drift = min(shape[1]*0.02, shape[2]*0.02) 67 68 img = generate_image(n_objects=n_objects, shape=shape, dtype=dtype) 69 70 if drift_mode == "directional": 71 transformation_matrix = EuclideanTransform(translation=(-drift, -drift)) 72 for i in range(shape[0]-1): 73 img[i+1] = warp(img[i], transformation_matrix.inverse, order=3, preserve_range=True) 74 75 elif drift_mode == "random": 76 for i in range(shape[0]-1): 77 78 state = np.random.randint(0, 3) 79 80 if state == 1: 81 transformation_matrix = EuclideanTransform(translation=(-sqrt(drift), -sqrt(drift))) 82 elif state == 2: 83 transformation_matrix = EuclideanTransform(translation=(-sqrt(drift), sqrt(drift))) 84 elif state == 3: 85 transformation_matrix = EuclideanTransform(translation=(sqrt(drift), -sqrt(drift))) 86 else: 87 transformation_matrix = EuclideanTransform(translation=(sqrt(drift), sqrt(drift))) 88 89 img[i+1] = warp(img[i], transformation_matrix.inverse, order=3, preserve_range=True) 90 91 return img
Generate random timelapse image with drift over time.
Parameters
- n_objects: int; number of objects to generate
- shape: tuple; with shape (t, y, x)
- dtype: data type to be used in the generated numpy array
- drift: None or int; number of pixels corresponding to drift between frames. If None, automatic drift is calculated based on 0.02 of image dimensions.
- drift_mode: str; "directional" (default) or "random";
Returns
numpy array with shape (t, y, x) and defined data type and n_objects
def
generate_channel_misalignment():
93def generate_channel_misalignment(): 94 """ 95 Generates an image with shape (3, 300, 300) with 1 object centered on each 3x3 block of the image. 96 Slices corresponding to channel 2 and 3 are shifted relative to channel 1 (template). 97 :return: numpy array of shape (3, 300, 300) corresponding to a random image with misalignment between channels. 98 """ 99 100 n_blocks = 3 101 h = 300 102 w = 300 103 104 block_img = np.zeros((int(h/n_blocks), int(w/n_blocks))) 105 block_h = int(h / n_blocks) 106 block_w = int(w / n_blocks) 107 block_img[int(block_h/2), int(block_w/2)] = 1 108 block_img = gaussian(block_img, sigma=3) 109 110 ref_channel = np.zeros((h, w)) 111 misaligned_blocks = [] 112 misaligned_blocks_2 = [] 113 114 for x_i in range(n_blocks): 115 for y_i in range(n_blocks): 116 ref_channel[y_i*block_h:y_i*block_h+block_h, x_i*block_w:x_i*block_w+block_w] += block_img 117 118 misalignments = [(-3, -3), (-3, 0), (-3, 3), (0, -3), (0, 0), (0, 3), (3, -3), (3, 0), (3, 3)] 119 120 for mis in misalignments: 121 block_img = np.zeros((int(h/n_blocks), int(w/n_blocks))) 122 block_h = h / n_blocks 123 block_w = w / n_blocks 124 block_img[int(block_h/2)+mis[0], int(block_w/2)+mis[1]] = 1 125 block_img = gaussian(block_img, sigma=3) 126 misaligned_blocks.append(block_img) 127 128 misalignments.reverse() 129 130 for mis in misalignments: 131 block_img = np.zeros((int(h/n_blocks), int(w/n_blocks))) 132 block_h = h / n_blocks 133 block_w = w / n_blocks 134 block_img[int(block_h/2)+mis[0], int(block_w/2)+mis[1]] = 1 135 block_img = gaussian(block_img, sigma=3) 136 misaligned_blocks_2.append(block_img) 137 138 misaligned_channel = assemble_frame_from_blocks(np.array(misaligned_blocks), 3, 3) 139 misaligned_channel_2 = assemble_frame_from_blocks(np.array(misaligned_blocks_2), 3, 3) 140 141 return np.array([ref_channel, misaligned_channel, misaligned_channel_2]).astype(np.float16)
Generates an image with shape (3, 300, 300) with 1 object centered on each 3x3 block of the image. Slices corresponding to channel 2 and 3 are shifted relative to channel 1 (template).
Returns
numpy array of shape (3, 300, 300) corresponding to a random image with misalignment between channels.